#ifndef RP2PROGRAM_H
#define RP2PROGRAM_H

#include "Rp2Object.h"
#include "Rp2Attributes.h"
#include "Rp2Bindable.h"
#include "Rp2NumericalConstant.h"
#include "Rp2RendererConstant.h"
#include "Rp2SamplerInformation.h"
#include "Rp2UserConstant.h"

// Cg compiler
#include <Cg/cg.h>   
#include <Cg/cgGL.h>

namespace Rp2
{

class Program : public Object, public Bindable
{
	RP2_DECLARE_RTTI;
	RP2_DECLARE_NAME_ID;

public:
	// Abstract base class
	virtual ~Program();

	// Member Read-Only access
	
	// Access to program text string
	const std::string& GetProgramText() const;
	
    // Access to the program input and output attributes.
    const Attributes& GetInputAttributes () const;
    const Attributes& GetOutputAttributes () const;

    // Access to renderer constants.
    int GetRendererConstantQuantity () const;
    RendererConstant* GetRendererConstant (int i);
    RendererConstant* GetRendererConstant (RendererConstant::Type eType);

    // Access to numerical constants.
    int GetNumericalConstantQuantity () const;
    NumericalConstant* GetNumericalConstant (int i);

    // Access to user constants.
    int GetUserConstantQuantity () const;
    UserConstant* GetUserConstant (int i);
    UserConstant* GetUserConstant (const std::string& rkName);

    // Access to samplers.
    int GetSamplerInformationQuantity () const;
    SamplerInformation* GetSamplerInformation (int i);
    SamplerInformation* GetSamplerInformation (const std::string& rkName);

	// This information is used to load and parse programs.
    static std::string RendererType;
    static char CommentChar;

    static bool Load (const std::string& rkFilename, Program* pkProgram);

	// Support for compile a cg program.
	// The compiled file will be saved at current directory on the disk.
	static bool CompileCg(const std::string& rkFilename);
	static bool CheckCgError(const std::string& rkError, CGcontext kCgContext,
		const std::string& rkFilename);

protected:
    // Streaming Support.
    Program ();

    // The program itself, stored as a text string.
    std::string m_kProgramText;

    // The format of the input and output parameters to the shader program.
    Attributes m_kInputAttributes;
    Attributes m_kOutputAttributes;

    // The renderer constants required by the shader program.
    std::vector<RendererConstant> m_kRendererConstants;

    // The numerical constants required by the shader program.
    std::vector<NumericalConstant> m_kNumericalConstants;

    // The user constants required by the shader program.  These are set by
    // the applications as needed.
    std::vector<UserConstant> m_kUserConstants;

    // Information about the sampler units required by a shader program.
    std::vector<SamplerInformation> m_kSamplerInformation;

    // For use by the constructor for loading and parsing a shader program.
    static const std::string ms_kFloatStr;
    static const std::string ms_kFloat1Str;
    static const std::string ms_kFloat1x1Str;
    static const std::string ms_kFloat1x2Str;
    static const std::string ms_kFloat1x3Str;
    static const std::string ms_kFloat1x4Str;
    static const std::string ms_kFloat2Str;
    static const std::string ms_kFloat2x1Str;
    static const std::string ms_kFloat2x2Str;
    static const std::string ms_kFloat2x3Str;
    static const std::string ms_kFloat2x4Str;
    static const std::string ms_kFloat3Str;
    static const std::string ms_kFloat3x1Str;
    static const std::string ms_kFloat3x2Str;
    static const std::string ms_kFloat3x3Str;
    static const std::string ms_kFloat3x4Str;
    static const std::string ms_kFloat4Str;
    static const std::string ms_kFloat4x1Str;
    static const std::string ms_kFloat4x2Str;
    static const std::string ms_kFloat4x3Str;
    static const std::string ms_kFloat4x4Str;
    static const std::string ms_kSampler1DStr;
    static const std::string ms_kSampler2DStr;
    static const std::string ms_kSampler3DStr;
    static const std::string ms_kSamplerCubeStr;
    static const std::string ms_kSamplerProjStr;
    static const std::string ms_kPositionStr;
    static const std::string ms_kBlendWeightStr0;
    static const std::string ms_kBlendWeightStr1;
    static const std::string ms_kNormalStr;
    static const std::string ms_kColorStr;
    static const std::string ms_kColor0Str;
    static const std::string ms_kColor1Str;
    static const std::string ms_kFogCoordStr;
    static const std::string ms_kFogStr;
    static const std::string ms_kPSizeStr;
    static const std::string ms_kBlendIndicesStr;
    static const std::string ms_kTexCoordStr;
    static const std::string ms_kTangentStr;
    static const std::string ms_kBinormalStr;
    static const std::string ms_kWPosStr;
    static const std::string ms_kInStr;
    static const std::string ms_kEOL;
};

typedef Pointer<Program> ProgramPtr;
#include "Rp2Program.inl"

}

#endif